package com.cseg674.dataquery;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set; 
import java.io.*;

import edu.stanford.smi.protegex.owl.jena.JenaOWLModel; 
import edu.stanford.smi.protegex.owl.model.OWLNamedClass;
import edu.stanford.smi.protegex.owl.model.OWLObjectProperty; 
import edu.stanford.smi.protegex.owl.model.impl.DefaultOWLNamedClass;
import edu.stanford.smi.protegex.owl.model.impl.DefaultOWLUnionClass;
import edu.stanford.smi.protegex.owl.ProtegeOWL;

 
public class Owl 
{ 
	private JenaOWLModel owlModel; 
	
	public Owl(String path){
		try{
			File f = new File(path);
			FileInputStream fis = new FileInputStream(f);
			owlModel = ProtegeOWL.createJenaOWLModelFromInputStream(fis);
		}
		catch (Exception e){ 
			 e.printStackTrace();
		}
	}
	
	public ArrayList<String> extractAllSubject(){
		ArrayList<String> subjList = new ArrayList<String>();
		try{
			if(owlModel != null){
				Iterator it = owlModel.getUserDefinedOWLNamedClasses().iterator();
				while(it.hasNext()){
					subjList.add(((OWLNamedClass)it.next()).getBrowserText());
				}
			}
		}
		catch (Exception e){
			 e.printStackTrace();
		}
		return subjList;
	}
	
	public ArrayList<String> extractAllObject(){
		return extractAllSubject();
	}
	
	public ArrayList<String> extractAllPredicate(){
		ArrayList<String> predList = new ArrayList<String>();
		try{
			if(owlModel != null){
				
				// Get all object properties
				Iterator pIt = owlModel.getUserDefinedOWLObjectProperties().iterator();
				OWLObjectProperty owlProp = null;
				
				while(pIt.hasNext()){
					owlProp = (OWLObjectProperty)pIt.next();
					String pName = owlProp.getBrowserText(); 
					predList.add(pName);			 
				}
			}
		}
		catch (Exception e){
			 e.printStackTrace();
		}
		return predList;
	}
	
	public ArrayList<String[]> extractSubjObjByPred(String predName){
		ArrayList<String[]> predList = new ArrayList<String[]>();
		ArrayList<String> subjList = new ArrayList<String>();
		ArrayList<String> objList = new ArrayList<String>();
		try{
			if(owlModel != null){
				 	
				subjList = extractSubject(predName);
				objList = extractObject(predName);
				
				// Transfer ArrayList to String array
				String[] subjArray = new String[subjList.size()];
				for(int i=0; i < subjList.size(); i++){
					subjArray[i] = subjList.get(i);
				}
					
				String[] objArray = new String[objList.size()];
				for(int i=0; i < objList.size(); i++){
					objArray[i] = objList.get(i);
				}
					
				predList.add(subjArray);
				predList.add(objArray);
		
			}
		}
		catch (Exception e){
			 e.printStackTrace();
		}
		return predList;
	}
	
	
	public ArrayList<String> extractPredBySubj(String subjName){
		ArrayList<String> predList = new ArrayList<String>();
		try{
			if(owlModel != null){
				
				// Get all object properties
				Iterator pIt = owlModel.getUserDefinedOWLObjectProperties().iterator();
				OWLObjectProperty owlProp = null;
				
				while(pIt.hasNext()){
					owlProp = (OWLObjectProperty)pIt.next();
					String pName = owlProp.getBrowserText(); 
					
					Iterator cIt = owlProp.getDomain().iterator();
					
					subjloop:
					while(cIt.hasNext()){
						Object owlObj = cIt.next();
						if(owlObj instanceof DefaultOWLNamedClass){
							DefaultOWLNamedClass owlCls = (DefaultOWLNamedClass)owlObj;
							if(owlCls.getName().equals(subjName)){
								predList.add(pName);
								break subjloop;
							}
						}
						else if(owlObj instanceof DefaultOWLUnionClass){
							DefaultOWLUnionClass owlUnCls = (DefaultOWLUnionClass)owlObj;
							Set s = new HashSet();
							owlUnCls.getNestedNamedClasses(s);
							Iterator nsIt = s.iterator();
							while(nsIt.hasNext()){
								DefaultOWLNamedClass owlNestedCls = (DefaultOWLNamedClass)nsIt.next();
								if(owlNestedCls.getName().equals(subjName)){
									predList.add(pName);
									break subjloop;
								}
							}
						}
					}	
				}
			}
		}
		catch (Exception e){
			 e.printStackTrace();
		}
		return predList;
	}
	
	public ArrayList<String> extractPredByObj(String objName){
		ArrayList<String> predList = new ArrayList<String>();
		try{
			if(owlModel != null){
				
				// Get all object properties
				Iterator pIt = owlModel.getUserDefinedOWLObjectProperties().iterator();
				OWLObjectProperty owlProp = null;
				
				while(pIt.hasNext()){
					owlProp = (OWLObjectProperty)pIt.next();
					String pName = owlProp.getBrowserText(); 
					
					Iterator oIt = owlProp.getRanges(true).iterator();
					objloop:
					while(oIt.hasNext()){
						Object owlObj = oIt.next();
						if(owlObj instanceof DefaultOWLNamedClass){
							DefaultOWLNamedClass owlCls = (DefaultOWLNamedClass)owlObj;
							if(owlCls.getName().equals(objName)){
								predList.add(pName);
								break objloop;
							}
						}
						else if(owlObj instanceof DefaultOWLUnionClass){
							DefaultOWLUnionClass owlUnCls = (DefaultOWLUnionClass)owlObj;
							Set s = new HashSet();
							owlUnCls.getNestedNamedClasses(s);
							Iterator nsIt = s.iterator();
							while(nsIt.hasNext()){
								DefaultOWLNamedClass owlNestedCls = (DefaultOWLNamedClass)nsIt.next();
								if(owlNestedCls.getName().equals(objName)){
									predList.add(pName);
									break objloop;
								}
							}
						}
					}	
				}
			}
		}
		catch (Exception e){
			 e.printStackTrace();
		}
		return predList;
	}
	
	public ArrayList<String> extractSubject(String predName){
		ArrayList<String> subjList = new ArrayList<String>();
		try{
			if(owlModel != null){
				if(predName.equals("hasModifier")){
					subjList = extractAllSubject();
				}
				else{
					OWLObjectProperty owlProp = owlModel.getOWLObjectProperty(predName);
				
					if(owlProp != null){
						Iterator sIt = owlProp.getDomain().iterator();
						while(sIt.hasNext()){
							Object owlObj = sIt.next();
							if(owlObj instanceof DefaultOWLNamedClass){
								DefaultOWLNamedClass owlCls = (DefaultOWLNamedClass)owlObj;
								subjList.add(owlCls.getName()); 
							}
							else if(owlObj instanceof DefaultOWLUnionClass){
								DefaultOWLUnionClass owlUnCls = (DefaultOWLUnionClass)owlObj;
								Set s = new HashSet();
								owlUnCls.getNestedNamedClasses(s);
								Iterator nsIt = s.iterator();
								while(nsIt.hasNext()){
									DefaultOWLNamedClass owlNestedCls = (DefaultOWLNamedClass)nsIt.next();
									subjList.add(owlNestedCls.getName());
								}
							}
						}
					} // End if
				} // End if
			} // End if
		} // End try
		catch (Exception e){
			e.printStackTrace();
		}
		return subjList;
	}
	
	public ArrayList<String> extractObject(String predName){
		ArrayList<String> objList = new ArrayList<String>();
		try{
			if(owlModel != null){
				OWLObjectProperty owlProp = owlModel.getOWLObjectProperty(predName);
				
				if(owlProp != null){
					Iterator cIt = owlProp.getRanges(true).iterator();
					while(cIt.hasNext()){
						Object owlObj = cIt.next();
					
						if(owlObj instanceof OWLNamedClass){
							DefaultOWLNamedClass owlCls = (DefaultOWLNamedClass)owlObj;
							objList.add(owlCls.getName()); 
						}
						else if(owlObj instanceof DefaultOWLUnionClass){
							DefaultOWLUnionClass owlUnCls = (DefaultOWLUnionClass)owlObj;
							Set s = new HashSet();
							owlUnCls.getNestedNamedClasses(s);
							Iterator ncIt = s.iterator();
							while(ncIt.hasNext()){
								DefaultOWLNamedClass owlNestedCls = (DefaultOWLNamedClass)ncIt.next();
								objList.add(owlNestedCls.getName());
							}
						}
					} // End while	
				} // End if
			} // End if
		} // End try
		catch (Exception e){
			 e.printStackTrace();
		}
		return objList;
	}
	
}


